package rs.etf.es.algorithm;

import java.io.Serializable;
import java.util.ArrayList;

import rs.etf.es.algorithm.states.InstantiateNodeState;

public class RequestManager implements Serializable {

    public static RequestManager requestManager;

    public static RequestManager instance() {
	if (requestManager == null) {
	    requestManager = new RequestManager();
	}

	return requestManager;
    }

    private ArrayList<Instantiation> alreadyInstantiated;
    private ArrayList<Instantiation> toBeInstantiated;

    private Algorithm algorithm;

    private RequestManager() {
	alreadyInstantiated = new ArrayList<Instantiation>();
	toBeInstantiated = new ArrayList<Instantiation>();
    }

    public synchronized Instantiation takeNextInstatiation() {
	AlgorithmBlocker.instance().setStopEnabled(true);
	while (toBeInstantiated.size() == 0) {
	    try {
		AlgorithmBlocker.instance().setStopEnabled(true);
		wait();
	    } catch (InterruptedException e) {
		return null;
	    }
	}
	Instantiation current = toBeInstantiated.get(0);
	alreadyInstantiated.add(current);
	toBeInstantiated.remove(0);
	return current;
    }

    public ArrayList<Instantiation> getAlreadyInstantiated() {
	return alreadyInstantiated;
    }

    public void setAlreadyInstantiated(ArrayList<Instantiation> alreadyInstantiated) {
	this.alreadyInstantiated = alreadyInstantiated;
    }

    public ArrayList<Instantiation> getToBeInstantiated() {
	return toBeInstantiated;
    }

    public void setToBeInstantiated(ArrayList<Instantiation> toBeInstantiated) {
	this.toBeInstantiated = toBeInstantiated;
    }

    public synchronized void instantiateVariable(String variableName, String variableValue) {
	Instantiation inst = new Instantiation(variableName, variableValue);
	toBeInstantiated.add(inst);
	InstantiateNodeState newState = new InstantiateNodeState();
	newState.setAlgorithm(algorithm);
	newState.setInst(inst);
	algorithm.pushAlgorithmState(newState);
	notifyAll();
    }

    public boolean isNodeInRequest(Node child) {
	for (Instantiation i : alreadyInstantiated) {
	    if (i.getVariableName().equals(child.getName())) {
		return true;
	    }
	}
	return false;
    }

    public Algorithm getAlgorithm() {
	return algorithm;
    }

    public void setAlgorithm(Algorithm algorithm) {
	this.algorithm = algorithm;
    }

    public void invalidate() {
	requestManager = null;
    }

}
